package com.ecoolex.chinadutyfree.retailer.admin.graphql;

import java.util.List;
import java.util.stream.Collectors;

import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;

import com.ecoolex.chinadutyfree.retailer.admin.core.AdminConstant;
import com.ecoolex.chinadutyfree.retailer.entity.DeliveryManner;
import com.ecoolex.chinadutyfree.retailer.entity.DirectMailGoods;
import com.ecoolex.chinadutyfree.retailer.entity.DirectMailGoods.Column;
import com.ecoolex.chinadutyfree.retailer.entity.DirectMailGoodsAudit;
import com.ecoolex.chinadutyfree.retailer.entity.DirectMailGoodsDummy;
import com.ecoolex.chinadutyfree.retailer.entity.DirectMailGoodsProduct;
import com.ecoolex.chinadutyfree.retailer.entity.FreightTemplate;
import com.ecoolex.chinadutyfree.retailer.entity.GoodsAfterService;
import com.ecoolex.chinadutyfree.retailer.entity.GoodsProduct;
import com.ecoolex.chinadutyfree.retailer.entity.GoodsWithBLOBs;
import com.ecoolex.chinadutyfree.retailer.enums.DirectMailGoodsProductStatus;
import com.ecoolex.chinadutyfree.retailer.enums.DirectMailGoodsStatus;
import com.ecoolex.chinadutyfree.retailer.pojo.AddDirectMailGoodsDTO;
import com.ecoolex.chinadutyfree.retailer.pojo.AddDirectMailGoodsProductDTO;
import com.ecoolex.chinadutyfree.retailer.pojo.EditDirectMailGoodsDTO;
import com.ecoolex.chinadutyfree.retailer.pojo.EditDirectMailGoodsDummyDTO;
import com.ecoolex.chinadutyfree.retailer.pojo.EditDirectMailGoodsProductDTO;
import com.ecoolex.chinadutyfree.retailer.pojo.QueryDirectMailGoodsDTO;
import com.ecoolex.chinadutyfree.retailer.ws.DeliveryService;
import com.ecoolex.chinadutyfree.retailer.ws.DirectMailGoodsService;
import com.ecoolex.chinadutyfree.retailer.ws.GoodsService;
import com.ecoolex.framework.common.annotation.Description;
import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.util.Assert;
import com.ecoolex.framework.common.util.BeanUtil;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.framework.modularize.api.auth.admin.AdminMemberAuthority;
import com.ecoolex.framework.modularize.api.auth.annotation.AdminAuthoritativeRegister;
import com.ecoolex.framework.modularize.api.service.currency.CurrencyType;
import com.ecoolex.framework.modularize.api.service.currency.CurrencyTypeService;
import com.ecoolex.framework.modularize.api.service.storage.FileSize;
import com.ecoolex.framework.modularize.api.service.storage.MimeType;
import com.ecoolex.framework.modularize.api.service.storage.StorageInfo;
import com.ecoolex.framework.modularize.api.service.storage.StorageService;
import com.ecoolex.framework.modularize.api.service.storage.Upload;
import com.ecoolex.framework.modularize.api.service.storage.UploadLimit;
import com.ecoolex.framework.modularize.api.service.storage.UploadSource;
import com.ecoolex.framework.web.api.graphql2.annotation.GraphQL2Module;
import com.ecoolex.framework.web.api.graphql2.annotation.GraphQL2Module.Type;
import com.ecoolex.framework.web.api.graphql2.annotation.MutationField;
import com.ecoolex.framework.web.api.graphql2.annotation.QueryField;
import com.ecoolex.framework.web.api.graphql2.annotation.Source;
import com.ecoolex.framework.web.api.graphql2.annotation.TypeField;
import com.google.common.collect.Lists;


@GraphQL2Module(type = Type.Admin, description = "直邮商品管理")
@AdminAuthoritativeRegister(parentKey = AdminConstant.AUTH_MODULE_KEY,
	key = DirectMailGoodsGraphql.AUTH,
	name = "直邮商品管理")
public class DirectMailGoodsGraphql {

	public static final String AUTH = AdminConstant.AUTH_MODULE_KEY + "-DIRECT-MAIL-GOODS";

	@Reference
	private DirectMailGoodsService service;

	@Reference
	private GoodsService goodsService;

	@Reference
	private DeliveryService deliveryService;

	@Autowired
	private CurrencyTypeService currencyTypeService;

	@Autowired
	private StorageService storageService;

	@TypeField(type = DirectMailGoods.class, field = "goods", description = "商品")
	public GoodsWithBLOBs goods(@Source DirectMailGoods source) {
		return goodsService.getGoodsById(source.getGoodsId());
	}

	@TypeField(type = DirectMailGoods.class, field = "currencyType", description = "币种")
	public CurrencyType currencyType(@Source DirectMailGoods source) {
		return currencyTypeService.get(source.getCurrencyType());
	}

	@TypeField(type = DirectMailGoods.class, field = "freightTemplate", description = "运费模板")
	public FreightTemplate freightTemplate(@Source DirectMailGoods source) {
		return deliveryService.getFreightTemplateById(source.getFreightTemplateId());
	}

	@TypeField(type = DirectMailGoods.class, field = "afterService", description = "售后服务模板")
	public GoodsAfterService afterService(@Source DirectMailGoods source) {
		if (Check.notNull(source.getAfterServiceId())) {
			return goodsService.getAfterServiceById(source.getAfterServiceId());
		} else {
			return null;
		}
	}

	@TypeField(type = DirectMailGoods.class, field = "dummy", description = "虚拟配置")
	public DirectMailGoodsDummy dummy(@Source DirectMailGoods source) {
		return service.getDummyByDirectMailGoodsId(source.getDirectMailGoodsId());
	}

	@TypeField(type = DirectMailGoods.class, field = "totalStockNumber", description = "总计库存(额定库存数量)")
	public Long totalStockNumber(@Source DirectMailGoods source) {
		return service.sumStockNumberByDirectMailGoodsId(source.getDirectMailGoodsId());
	}

	@TypeField(type = DirectMailGoods.class, field = "totalUsedStockNumber", description = "总计使用库存(销售数量+冻结库存)")
	public Long sumUsedStockNumber(@Source DirectMailGoods source) {
		return service.sumUsedStockNumberByDirectMailGoodsId(source.getDirectMailGoodsId());
	}

	@TypeField(type = DirectMailGoods.class, field = "totalSoldNumber", description = "总计销售数量")
	public Long sumSoldNumber(@Source DirectMailGoods source) {
		return service.sumSoldNumberByDirectMailGoodsId(source.getDirectMailGoodsId());
	}

	@TypeField(type = DirectMailGoods.class, field = "productList", description = "产品集合")
	public List<DirectMailGoodsProduct> productList(@Source DirectMailGoods source) {
		return service.queryProductAllStatusByDirectMailGoodsId(source.getDirectMailGoodsId());
	}

	@TypeField(type = DirectMailGoods.class, field = "deliveryMannerList", description = "配送方式集合")
	public List<DeliveryManner> deliveryMannerList(@Source DirectMailGoods source) {
		return service.queryDeliveryMannerByDirectMailGoodsId(source.getDirectMailGoodsId()).stream().map(
			dm -> deliveryService.getDeliveryMannerById(dm.getDeliveryMannerId())).collect(Collectors.toList());
	}

	@TypeField(type = DirectMailGoods.class, field = "canRelease", description = "是否能上线")
	public boolean canRelease(@Source DirectMailGoods source) {
		return DirectMailGoodsStatus.RELEASE.notEqual(source.getStatus());
	}

	@TypeField(type = DirectMailGoods.class, field = "canOffline", description = "是否能下线")
	public boolean canOffline(@Source DirectMailGoods source) {
		return DirectMailGoodsStatus.RELEASE.equal(source.getStatus());
	}

	@TypeField(type = DirectMailGoods.class, field = "canDelete", description = "是否能删除")
	public boolean canDelete(@Source DirectMailGoods source) {
		return DirectMailGoodsStatus.RELEASE.notEqual(source.getStatus());
	}

	@TypeField(type = DirectMailGoodsProduct.class, field = "product", description = "产品")
	public GoodsProduct product(@Source DirectMailGoodsProduct source) {
		return goodsService.getGoodsProductById(source.getProductId());
	}

	@TypeField(type = DirectMailGoodsProduct.class, field = "canEdit", description = "是否能编辑")
	public boolean canEdit(@Source DirectMailGoodsProduct source) {
		return DirectMailGoodsProductStatus.OFFLINE.notEqual(source.getStatus());
	}

	private static final String AUTH_GET = AUTH + "-GET";

	@QueryField(field = "directMailGoods", description = { "获取直销商品详情" })
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_GET, name = "获取直销商品详情")
	public DirectMailGoods get(@NonNull Integer directMailGoodsId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_GET);
		return service.getById(directMailGoodsId);
	}

	@QueryField(field = "directMailGoodsProductList",
		description = { "查询直销商品产品列表",
			AUTH_GET })
	public List<DirectMailGoodsProduct> directMailGoodsProductList(@NonNull Integer directMailGoodsId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_GET);
		return service.queryProductAllStatusByDirectMailGoodsId(directMailGoodsId);
	}

	@QueryField(field = "directMailGoodsDummy",
		description = { "获取直销商品虚拟配置详情",
			AUTH_GET })
	public DirectMailGoodsDummy directMailGoodsDummy(@NonNull Integer directMailGoodsId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_GET);
		return service.getDummyByDirectMailGoodsId(directMailGoodsId);
	}

	private static final String AUTH_QUERY = AUTH + "-QUERY";

	@QueryField(field = "directMailGoodsList", description = "查询直销商品列表")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_QUERY, name = "查询直销商品列表")
	public Pagination<DirectMailGoods> query(@NonNull QueryDirectMailGoodsDTO query, @NonNull Sorting[] sorts, @NonNull Page page, AdminMemberAuthority user) {
		user.assertAuth(AUTH_QUERY);
		return service.query(query, sorts, page);
	}

	@MutationField(field = "uploadDirectMailGoodsDetail", description = { "上传直销商品图片" })
	public StorageInfo uploadGoodsBrandLogo(@NonNull Upload request, AdminMemberAuthority user) {
		if (!user.auth(AUTH_ADD) && !user.auth(AUTH_EDIT)) {
            user.notAuthority();
        }
        UploadSource uploadSource = new UploadSource("DirectMailGoods", "Detail");
        UploadLimit uploadLimit = new UploadLimit();
        uploadLimit.setMaxSize(FileSize.MB.byteLength(2));
        uploadLimit.setAllowMimeType(MimeType.IMAGE.commons());

        return storageService.upload(request, uploadSource, uploadLimit);
	}
	
	private static final String AUTH_AUDIT_GET = AUTH + "-AUDIT-GET";

	@QueryField(field = "directMailGoodsAudit", description = { "获取直销商品审核记录详情" })
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_AUDIT_GET, name = "获取直销商品审核记录详情")
	public DirectMailGoodsAudit getAudit(@NonNull Integer auditId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_AUDIT_GET);
		return service.getAudit(auditId);
	}
	
	private static final String AUTH_AUDIT_QUERY = AUTH + "-AUDIT-QUERY";

	@QueryField(field = "directMailGoodsAuditList", description = { "获取直销商品审核记录列表" })
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_AUDIT_QUERY, name = "获取直销商品审核记录列表")
	public Pagination<DirectMailGoodsAudit> queryAudit(@NonNull Sorting[] sorts, @NonNull Page page, AdminMemberAuthority user) {
		user.assertAuth(AUTH_AUDIT_QUERY);
		return service.queryAudit(sorts, page);
	}
	
	private static final String AUTH_ADD = AUTH + "-ADD";

	@MutationField(field = "addDirectMailGoods", description = "添加直销商品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_ADD, name = "添加直销商品")
	public DirectMailGoods add(@NonNull AddDirectMailGoodsDTO add, @Description({
		"配送方式集合" }) @NonNull List<Integer> deliveryMannerList, AdminMemberAuthority user) {
		user.assertAuth(AUTH_ADD);
		return service.add(add, deliveryMannerList, user.userName());
	}

	private static final String AUTH_EDIT = AUTH + "-EDIT";

	@MutationField(field = "editDirectMailGoods", description = "编辑直销商品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_EDIT, name = "编辑直销商品")
	public DirectMailGoods edit(@NonNull EditDirectMailGoodsDTO edit, @Description({
		"配送方式集合" }) @NonNull List<Integer> deliveryMannerList, AdminMemberAuthority user) {
		user.assertAuth(AUTH_EDIT);
		DirectMailGoods record = service.getById(edit.getDirectMailGoodsId());
		Assert.isTrue(Check.notNull(record), ResultCode.VERIFY.build(1), "直销商品不存在");
		BeanUtil.copy(edit,
			record,
			Lists.newArrayList(Column.goodsId,
				Column.status,
				Column.deleted,
				Column.createUser,
				Column.createTime).stream().map(Column::getJavaProperty).toArray(String[]::new));
		return service.update(record, deliveryMannerList, user.userName());
	}

	private static final String AUTH_DEL = AUTH + "-DEL";

	@MutationField(field = "delDirectMailGoods", description = "删除直销商品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_DEL, name = "删除直销商品")
	public boolean del(@NonNull Integer directMailGoodsId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_DEL);
		DirectMailGoods record = service.getById(directMailGoodsId);
		Assert.isTrue(Check.notNull(record), ResultCode.VERIFY.build(1), "直销商品不存在");
		service.delete(record, user.userName());
		return true;
	}

	private static final String AUTH_RELEASE = AUTH + "-RELEASE";

	@MutationField(field = "releaseDirectMailGoods", description = "上线直销商品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_RELEASE, name = "上线直销商品")
	public DirectMailGoods releaseDirectMailGoods(@NonNull Integer directMailGoodsId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_RELEASE);
		DirectMailGoods record = service.getById(directMailGoodsId);
		Assert.isTrue(Check.notNull(record), ResultCode.VERIFY.build(1), "直销商品不存在");
		return service.release(record, user.userName());
	}

	private static final String AUTH_OFFLINE = AUTH + "-OFFLINE";

	@MutationField(field = "offlineDirectMailGoods", description = "下线直销商品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_OFFLINE, name = "下线直销商品")
	public DirectMailGoods offlineDirectMailGoods(@NonNull Integer directMailGoodsId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_OFFLINE);
		DirectMailGoods record = service.getById(directMailGoodsId);
		Assert.isTrue(Check.notNull(record), ResultCode.VERIFY.build(1), "直销商品不存在");
		return service.offline(record, user.userName());
	}
	
	private static final String AUTH_AUDIT_AGGREE = AUTH + "-AUDIT-AGGREE";

	@MutationField(field = "agreeDirectMailGoodsRelease", description = "审核同意直销商品上线")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_AUDIT_AGGREE, name = "审核同意直销商品上线")
	public DirectMailGoods agreeDirectMailGoodsRelease(@NonNull Integer directMailGoodsId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_AUDIT_AGGREE);
		DirectMailGoods record = service.getById(directMailGoodsId);
		Assert.isTrue(Check.notNull(record), ResultCode.VERIFY.build(1), "直销商品不存在");
		return service.agreeDirectMailGoodsRelease(record, user.userName());
	}
	
	private static final String AUTH_AUDIT_REFUSE = AUTH + "-AUDIT-REFUSE";

	@MutationField(field = "refuseDirectMailGoodsRelease", description = "审核拒绝直销商品上线")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_AUDIT_REFUSE, name = "审核拒绝直销商品上线")
	public DirectMailGoods refuseDirectMailGoodsRelease(@NonNull Integer directMailGoodsId,@NonNull String auditOpinion, AdminMemberAuthority user) {
		user.assertAuth(AUTH_AUDIT_REFUSE);
		DirectMailGoods record = service.getById(directMailGoodsId);
		Assert.isTrue(Check.notNull(record), ResultCode.VERIFY.build(1), "直销商品不存在");
		return service.refuseDirectMailGoodsRelease(record, auditOpinion, user.userName());
	}
	
	private static final String AUTH_PRODUCT_ADD = AUTH + "-PRODUCT-ADD";

	@MutationField(field = "addDirectMailGoodsProduct", description = "添加直销商品产品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_PRODUCT_ADD, name = "添加直销商品产品")
	public DirectMailGoodsProduct addDirectMailGoodsProduct(@NonNull AddDirectMailGoodsProductDTO add, AdminMemberAuthority user) {
		user.assertAuth(AUTH_PRODUCT_ADD);
		DirectMailGoods goods = service.getById(add.getDirectMailGoodsId());
		Assert.isTrue(Check.notNull(goods), ResultCode.VERIFY.build(1), "直销商品不存在");
		return service.addProduct(goods, add, user.userName());
	}

	private static final String AUTH_PRODUCT_EDIT = AUTH + "-PRODUCT-EDIT";

	@MutationField(field = "editDirectMailGoodsProduct", description = "编辑直销商品产品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_PRODUCT_EDIT, name = "编辑直销商品产品")
	public DirectMailGoodsProduct addDirectMailGoodsProduct(@NonNull EditDirectMailGoodsProductDTO edit, AdminMemberAuthority user) {
		user.assertAuth(AUTH_PRODUCT_EDIT);
		DirectMailGoodsProduct record = service.getProductById(edit.getDirectMailProductId());
		Assert.isTrue(Check.notNull(record), ResultCode.VERIFY.build(1), "直销商品产品不存在");
		BeanUtil.copy(edit,
			record,
			Lists.newArrayList(DirectMailGoodsProduct.Column.directMailGoodsId,
				DirectMailGoodsProduct.Column.goodsId,
				DirectMailGoodsProduct.Column.productId,
				DirectMailGoodsProduct.Column.specNames,
				DirectMailGoodsProduct.Column.specSorting,
				DirectMailGoodsProduct.Column.usedStockNumber,
				DirectMailGoodsProduct.Column.soldNumber,
				DirectMailGoodsProduct.Column.status,
				DirectMailGoodsProduct.Column.deleted,
				DirectMailGoodsProduct.Column.createUser,
				DirectMailGoodsProduct.Column.createTime).stream().map(
					DirectMailGoodsProduct.Column::getJavaProperty).toArray(String[]::new));
		return service.updateProduct(record, user.userName());
	}

	private static final String AUTH_PRODUCT_DEL = AUTH + "-PRODUCT-DEL";

	@MutationField(field = "delDirectMailGoodsProduct", description = "删除直销商品产品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_PRODUCT_DEL, name = "删除直销商品产品")
	public Boolean delDirectMailGoodsProduct(@NonNull Integer directMailProductId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_PRODUCT_DEL);
		DirectMailGoodsProduct record = service.getProductById(directMailProductId);
		Assert.isTrue(Check.notNull(record), ResultCode.VERIFY.build(1), "直销商品产品不存在");
		service.deleteProduct(record, user.userName());
		return true;
	}

	private static final String AUTH_DUMMY_EDIT = AUTH + "-DUMMY-EDIT";

	@MutationField(field = "editDirectMailGoodsDummy", description = "编辑直销商品虚拟配置")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_DUMMY_EDIT, name = "编辑直销商品虚拟配置")
	public DirectMailGoodsDummy editDirectMailGoodsDummy(@NonNull EditDirectMailGoodsDummyDTO edit, AdminMemberAuthority user) {
		user.assertAuth(AUTH_DUMMY_EDIT);

		DirectMailGoodsDummy record = service.getDummyByDirectMailGoodsId(edit.getDirectMailGoodsId());
		Assert.isTrue(Check.notNull(record), ResultCode.VERIFY.build(1), "直销商品虚拟配置不存在");
		BeanUtil.copy(edit,
			record,
			Lists.newArrayList(DirectMailGoodsDummy.Column.deleted,
				DirectMailGoodsDummy.Column.createUser,
				DirectMailGoodsDummy.Column.createTime).stream().map(
					DirectMailGoodsDummy.Column::getJavaProperty).toArray(String[]::new));
		return service.updateDummy(record, user.userName());
	}
}

